package bmatch.tech;

import bmatch.tech.Utils.IDUtils;
import bmatch.tech.model.UploadFile;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

@MultipartConfig
public class UploadServlet extends HttpServlet {
    /**
     * 文件映射
     */
    private static ObjectMapper objectMapper = new ObjectMapper();
    /**
     * 存储
     */
    private static File file = new File("./files.json");
    /**
     * 缓存
     */
    private static List<UploadFile> caches;

    public static List<UploadFile> getCaches() {
        return caches;
    }


    static {
        try {
            caches = objectMapper.readValue(file, new TypeReference<List<UploadFile>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setStatus(200);
        resp.getWriter().print("<h1>No Get!<h2>");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("doPost");
        boolean isMultipart = ServletFileUpload.isMultipartContent(req);
        if (isMultipart) {
            System.out.println("True");

            // 创建工厂（这里用的是工厂模式）
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //获取汽车零件清单与组装说明书（从ServletContext中得到上传来的数据）
            ServletContext servletContext = this.getServletConfig().getServletContext();
            File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
            //工厂把将要组装的汽车的参数录入工厂自己的系统，因为要根据这些参数开设一条生产线（上传来的文件的各种属性）
            factory.setRepository(repository);
            //此时工厂中已经有了汽车的组装工艺、颜色等属性参数（上传来的文件的大小、文件名等）
            //执行下面的这一行代码意味着根据组装工艺等开设了一条组装生产线
            ServletFileUpload upload = new ServletFileUpload(factory);

            //解析请求
            try {
                //把零件送给生产线，出来的就是一辆组装好的汽车（把request转成FileItem的实例）
                List<FileItem> items = upload.parseRequest(req);
                Iterator<FileItem> iter = items.iterator();

                FileItem item = iter.next();
                String contentType = item.getContentType();
                String name = item.getName();
                String suffix = name.substring(name.lastIndexOf("."), name.length());
                String uuid = IDUtils.getId();

                //创建文件输出流
                File file = new File("./" + uuid + suffix);
                if (!file.exists()) {
                    try {
                        file.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }


                FileOutputStream fos = new FileOutputStream(file);
                //创建输入流
                InputStream fis = (InputStream) item.getInputStream();
                //从输入流获取字节数组
                byte b[] = new byte[1];
                //读取一个输入流的字节到b[0]中
                int read = fis.read(b);
                while (read != -1) {
                    fos.write(b, 0, 1);
                    read = fis.read(b);
                }
                fis.close();
                fos.flush();
                fos.close();

                //添加信息到缓存
                UploadFile uploadFile = new UploadFile();
                uploadFile.setId(uuid);
                uploadFile.setGmtUploadDate(new Date());
                uploadFile.setName(name);
                uploadFile.setMimeType(contentType);
                uploadFile.setStoreFileName(uuid + suffix);
                caches.add(uploadFile);
                store();

                resp.setContentType("text/html");
                resp.setStatus(200);
                resp.getWriter().print("<h1>Upload Finished!<h1>");

            } catch (FileUploadException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("False");
        }
    }


    /**
     * 文件保存
     */
    public static void store() {
        if (caches == null) {
            return;
        }
        try {
            objectMapper.writeValue(file, caches);
        } catch (IOException e) {
        }
    }

}
